package br.uniceub.fsw.agenda.model.facade;

import br.uniceub.fsw.agenda.exception.BusinessException;
import br.uniceub.fsw.agenda.exception.DatabaseException;
import br.uniceub.fsw.agenda.model.dao.BairroDAO;
import br.uniceub.fsw.agenda.model.dao.CidadeDAO;
import br.uniceub.fsw.agenda.model.dao.LogradouroDAO;
import br.uniceub.fsw.agenda.model.dao.MenuDAO;
import br.uniceub.fsw.agenda.model.dao.TipoLogradouroDAO;
import br.uniceub.fsw.agenda.model.dao.UFDAO;
import br.uniceub.fsw.agenda.model.vo.BairroVO;
import br.uniceub.fsw.agenda.model.vo.CidadeVO;
import br.uniceub.fsw.agenda.model.vo.MenuVO;
import br.uniceub.fsw.agenda.model.vo.TipoLogradouroVO;
import br.uniceub.fsw.agenda.model.vo.UFVO;
import br.uniceub.fsw.agenda.model.vo.LogradouroVO;
import br.uniceub.fsw.agenda.util.StringUtils;
import java.util.ArrayList;
import java.util.List;

/**
 * 05/04/2008
 * @author Rodrigo Uchôa - rodrigo.uchoa@yahoo.com
 *
 */
public class ManterLogradouroFacade extends GenericFacade {

    /**
     * Busca todas os Menus
     * @return List com objetos Menu
     * @throws br.uniceub.fsw.agenda.exception.DatabaseException
     * @throws br.uniceub.fsw.agenda.exception.BusinessException
     */
    public List<MenuVO> findAllMenu() throws DatabaseException, BusinessException {
        try {
            MenuDAO dao = new MenuDAO(getConnection());
            return dao.findAll();
        } finally {
            closeConnection();
        }
    }
    
    /**
     * Busca todos os bairros de uma cidade especifica ordenados
     * por ordem alfabetica
     * @param idCidade código da cidade
     * @return List com objetos Bairro
     * @throws br.uniceub.fsw.agenda.exception.DatabaseException
     */
    public List<BairroVO> findBairrosByCidade(Integer idCidade) throws DatabaseException {
        try {
            //metodo getConnection() é herdado da super classe
            BairroDAO dao = new BairroDAO(getConnection());
            return dao.findBairrosByCidade(idCidade);
        } finally {
            //fechar conexao depois de usar
            closeConnection();
        }
    }

    /**
     * Busca todos os bairros de uma cidade especifica ordenados
     * por ordem alfabetica
     * @param idCidade código da cidade
     * @return List com objetos Bairro
     * @throws br.uniceub.fsw.agenda.exception.DatabaseException
     */
    public List<BairroVO> findAllBairro(Integer idCidade) throws DatabaseException {
        try {
            //metodo getConnection() é herdado da super classe
            BairroDAO dao = new BairroDAO(getConnection());
            
            if(idCidade == null) {
                return dao.findAll();
            } else {
                return dao.findAllByCidade(idCidade);
            }
        } finally {
            //fechar conexao depois de usar
            closeConnection();
        }
    }

    /**
     * Busca lista de cidades de uma UF especifica ordenadas por ordem
     * alfabetica.
     * @param siglaUF sigla da UF
     * @return List com objetos Cidade
     * @throws br.uniceub.fsw.agenda.exception.BusinessException
     * @throws br.uniceub.fsw.agenda.exception.DatabaseException
     */
    public List<CidadeVO> findCidadesByUF(String siglaUF)
            throws BusinessException, DatabaseException {
        try {
            //metodo getConnection e herdado da super classe
            CidadeDAO dao = new CidadeDAO(getConnection());
            return dao.findCidadesByUF(siglaUF);

        } finally {
            //sempre fechar conexao depois de usar
            closeConnection();
        }

    }
    
    /**
     * Busca lista de cidades de uma UF especifica ordenadas por ordem
     * alfabetica.
     * @param siglaUF sigla da UF
     * @return List com objetos Cidade
     * @throws br.uniceub.fsw.agenda.exception.BusinessException
     * @throws br.uniceub.fsw.agenda.exception.DatabaseException
     */
    public List<CidadeVO> findAllCidade(String sgUf)
            throws BusinessException, DatabaseException {
        try {
            //metodo getConnection e herdado da super classe
            CidadeDAO dao = new CidadeDAO(getConnection());
            
            if(StringUtils.isNullOrEmpty(sgUf)) {
                return dao.findAll();
            } else {
                return dao.findCidadesByUF(sgUf);
            }
            
        } finally {
            //sempre fechar conexao depois de usar
            closeConnection();
        }

    }
    
    /**
     * Busca todas as UFs
     * @return List com objetos UF
     * @throws br.uniceub.fsw.agenda.exception.DatabaseException
     * @throws br.uniceub.fsw.agenda.exception.BusinessException
     */
    public List<UFVO> findAllUFs() throws DatabaseException, BusinessException {
        try {
            UFDAO dao = new UFDAO(getConnection());
            return dao.findAll();
        } finally {
            closeConnection();
        }
    }
    
    /**
     * Busca todos os tipos de logradouro
     * @return List com objetos TipoLogradouro
     * @throws br.uniceub.fsw.agenda.exception.DatabaseException
     * @throws br.uniceub.fsw.agenda.exception.BusinessException
     */
    public List<TipoLogradouroVO> findAllTiposLogradouro() throws DatabaseException, BusinessException {
        try {
            TipoLogradouroDAO dao = new TipoLogradouroDAO(getConnection());
            return dao.findAll();
        } finally {
            closeConnection();
        }
    }
    
    /**
     * Retorna todos os logradouros cadastrados para serem exibidos na grid de
     * consulta.
     * 
     * DAO's de diferentes entidades serao usados para montar uma colecao de
     * VOLogradouro's, simplicando a visao que a web tier tem das entidades
     * do sistema.
     * @return List contendo objetos VOLogradouro
     * @throws br.uniceub.fsw.agenda.exception.DatabaseException
     */
    public List<LogradouroVO> findAllLogradourosCadastradosParaExibicao() throws DatabaseException {
        try {            
            //lista pra armazenar o resultado
            List<LogradouroVO> listResultado = new ArrayList<LogradouroVO>();
            
            //daos
            LogradouroDAO daoLogradouro = new LogradouroDAO(getConnection());
            UFDAO daoUF = new UFDAO(getConnection());
            CidadeDAO daoCidade = new CidadeDAO(getConnection());
            BairroDAO daoBairro = new BairroDAO(getConnection());
            TipoLogradouroDAO daoTipoLogradouro = new TipoLogradouroDAO(getConnection());
            
            //primeiro buscar todos os logradouros
            List<LogradouroVO> listLogradouros = daoLogradouro.findAll(); 
            //iterar pelos logradouros encontrados e pegar os objetos dependentes
            for (LogradouroVO logradouro : listLogradouros) {
                //pegar cidade desse logradouro
                CidadeVO cidade = daoCidade.findById(logradouro.getCidade().getIdCidade());
                //UF da cidade: como so a sigla é suficiente, nao precisa
                //fazer consulta
                UFVO uf = new UFVO();
                uf.setSgUf(cidade.getUf().getSgUf());
                //buscar bairro desse logradouro
                BairroVO bairro = null;
                
                if(logradouro.getBairro() != null) {
                    bairro = daoBairro.findById(logradouro.getBairro().getIdBairro());
                }
                //bairro nao é obrigatorio, se retornar null criar um objeto
                //vazio pra evitar NullPointerException na tela
                if (bairro == null) {
                    bairro = new BairroVO();
                }
                //buscar o tipo de logradouro
                TipoLogradouroVO tipoLogradouro = daoTipoLogradouro.findById(logradouro.getTipoLogradouro().getIdTipoLogradouro());
                
                //montar o VOLogradouro(Transfer Object Assembler) que sera usado na tela
                LogradouroVO vo = new LogradouroVO();
                vo.setCidade(cidade);
                vo.setUf(uf);
                vo.setTipoLogradouro(tipoLogradouro);
                vo.setBairro(bairro);
                vo.setIdLogradouro(logradouro.getIdLogradouro());
                vo.setNrCep(logradouro.getNrCep());
                vo.setDsLogradouro(logradouro.getDsLogradouro());
                
                //adicionar na lista do resultado
                listResultado.add(vo);
            }
            return listResultado;            
        } finally {
            closeConnection();
        }        
    }
    
    /**
     * Retorna todos os logradouros cadastrados para serem exibidos na grid de
     * consulta.
     * 
     * DAO's de diferentes entidades serao usados para montar uma colecao de
     * VOLogradouro's, simplicando a visao que a web tier tem das entidades
     * do sistema.
     * @return List contendo objetos VOLogradouro
     * @throws br.uniceub.fsw.agenda.exception.DatabaseException
     */
    public List<LogradouroVO> findAllLogradouro(String dsLogradouro, Integer nrCep) throws DatabaseException {
        try {            
            //lista pra armazenar o resultado
            List<LogradouroVO> listResultado = new ArrayList<LogradouroVO>();
            
            //daos
            LogradouroDAO daoLogradouro = new LogradouroDAO(getConnection());
            
            List<LogradouroVO> listLogradouros = null;
            
            if(nrCep != null) {
                LogradouroVO logradouro = daoLogradouro.findByCep(nrCep);
                listLogradouros = new ArrayList<LogradouroVO>();
                listLogradouros.add(logradouro);
            } else if (!StringUtils.isNullOrEmpty(dsLogradouro)) {
                listLogradouros = daoLogradouro.findByDsLogradouro(dsLogradouro);
            } else {
                listLogradouros = daoLogradouro.findAll();
            }
            
            return listLogradouros;
        } finally {
            closeConnection();
        }        
    }

    /**
     * Insere um novo logradouro.
     * @param logradouro
     * @return ID auto-increment gerada pra esse registro
     * @throws br.uniceub.fsw.agenda.exception.BusinessException 
     * @throws br.uniceub.fsw.agenda.exception.DatabaseException
     */
    public Integer insertLogradouro(LogradouroVO logradouro) throws BusinessException, DatabaseException {
        try {
            LogradouroDAO dao = new LogradouroDAO(getConnection());
            return dao.insert(logradouro);            
        } finally {
            closeConnection();
        }        
    }
    
    /**
     * Deletar o logradouro com o id especificado
     * @param idLogradouro
     * @throws br.uniceub.fsw.agenda.exception.BusinessException
     * @throws br.uniceub.fsw.agenda.exception.DatabaseException
     */
    public void deleteLogradouro(Integer idLogradouro) throws BusinessException,
            DatabaseException {
        try {
            LogradouroDAO dao = new LogradouroDAO(getConnection());
            dao.delete(idLogradouro);
        } finally {
            closeConnection();
        }        
    }
    
    /**
     * alterar dados do logradouro passado como parametro
     * @param logradouro 
     * @return objeto LogradouroVO alterado
     * @throws br.uniceub.fsw.agenda.exception.BusinessException
     * @throws br.uniceub.fsw.agenda.exception.DatabaseException
     */
    public LogradouroVO updateLogradouro(LogradouroVO logradouro) throws BusinessException,
            DatabaseException {
        try {
            LogradouroDAO dao = new LogradouroDAO(getConnection());
            return dao.update(logradouro);            
        } finally {
            closeConnection();
        }
    }
    
    public LogradouroVO findLogradouroById(Integer idLogradouro) throws DatabaseException {
        try {
            LogradouroDAO dao = new LogradouroDAO(getConnection());
            return dao.findById(idLogradouro);
        } finally {
            closeConnection();
        }
    }
}
